Remove the notion of "primary" from Context
authorAlex Crichton <alex@alexcrichton.com>
Mon, 6 Oct 2014 18:27:16 +0000 (11:27 -0700)
committerAlex Crichton <alex@alexcrichton.com>
Mon, 6 Oct 2014 18:27:16 +0000 (11:27 -0700)
Now that we have selective testing, this no longer makes any sense and all
queries to the path layout need to be based on the package being queried for.
This removes the primary flag from the Context, and requires that the `layout`
method have a local Package available

cc servo/servo#3580

src/cargo/ops/cargo_rustc/context.rs
src/cargo/ops/cargo_rustc/fingerprint.rs
src/cargo/ops/cargo_rustc/mod.rs
tests/test_cargo_test.rs

index cba02feff8d54054c0f494e56a37d73114787343..8f5d1d3ca647f3fc7faae7c577f29fb44b83d64a 100644 (file)
@@ -17,7 +17,6 @@ pub enum PlatformRequirement {
 }
 
 pub struct Context<'a, 'b> {
-    pub primary: bool,
     pub rustc_version: String,
     pub config: &'b mut Config<'b>,
     pub resolve: &'a Resolve,
@@ -59,7 +58,6 @@ impl<'a, 'b> Context<'a, 'b> {
             env: env,
             host: host,
             target: target,
-            primary: false,
             resolve: resolve,
             sources: sources,
             package_set: deps,
@@ -155,8 +153,10 @@ impl<'a, 'b> Context<'a, 'b> {
 
         self.compilation.extra_env.insert("NUM_JOBS".to_string(),
                                           Some(self.config.jobs().to_string()));
-        self.compilation.root_output = self.layout(KindTarget).proxy().dest().clone();
-        self.compilation.deps_output = self.layout(KindTarget).proxy().deps().clone();
+        self.compilation.root_output =
+                self.layout(pkg, KindTarget).proxy().dest().clone();
+        self.compilation.deps_output =
+                self.layout(pkg, KindTarget).proxy().deps().clone();
 
         return Ok(());
     }
@@ -186,19 +186,14 @@ impl<'a, 'b> Context<'a, 'b> {
             .map(|a| *a).unwrap_or(PlatformTarget)
     }
 
-    /// Switch this context over to being the primary compilation unit,
-    /// affecting the output of `dest()` and such.
-    pub fn primary(&mut self) {
-        self.primary = true;
-    }
-
     /// Returns the appropriate directory layout for either a plugin or not.
-    pub fn layout(&self, kind: Kind) -> LayoutProxy {
+    pub fn layout(&self, pkg: &Package, kind: Kind) -> LayoutProxy {
+        let primary = pkg.get_package_id() == self.resolve.root();
         match kind {
-            KindPlugin => LayoutProxy::new(&self.host, self.primary),
+            KindPlugin => LayoutProxy::new(&self.host, primary),
             KindTarget =>  LayoutProxy::new(self.target.as_ref()
                                                 .unwrap_or(&self.host),
-                                            self.primary)
+                                            primary)
         }
     }
 
index f1840da877dbf52e6d90b417c6876ffa46aa6311..7af5995b860f8fd1e22e5fa39ed30f1800465338 100644 (file)
@@ -82,7 +82,7 @@ pub fn prepare_target(cx: &mut Context, pkg: &Package, target: &Target,
     let is_rustc_fresh = try!(is_fresh(&old_loc, rustc_fingerprint.as_slice()));
 
     let (old_root, root) = {
-        let layout = cx.layout(kind);
+        let layout = cx.layout(pkg, kind);
         (layout.old_root().clone(), layout.root().clone())
     };
     let mut pairs = vec![(old_loc, new_loc.clone())];
@@ -151,10 +151,10 @@ pub fn prepare_build_cmd(cx: &mut Context, pkg: &Package)
 
     let is_fresh = try!(is_fresh(&old_loc, new_fingerprint.as_slice()));
     let pairs = vec![(old_loc, new_loc.clone()),
-                     (cx.layout(kind).old_native(pkg),
-                      cx.layout(kind).native(pkg))];
+                     (cx.layout(pkg, kind).old_native(pkg),
+                      cx.layout(pkg, kind).native(pkg))];
 
-    let native_dir = cx.layout(kind).native(pkg);
+    let native_dir = cx.layout(pkg, kind).native(pkg);
     cx.compilation.native_dirs.insert(pkg.get_package_id().clone(), native_dir);
 
     Ok(prepare(is_fresh, new_loc, new_fingerprint, pairs))
@@ -193,7 +193,7 @@ fn prepare(is_fresh: bool, loc: Path, fingerprint: String,
 
 /// Return the (old, new) location for fingerprints for a package
 pub fn dirs(cx: &Context, pkg: &Package, kind: Kind) -> (Path, Path) {
-    let layout = cx.layout(kind);
+    let layout = cx.layout(pkg, kind);
     let layout = layout.proxy();
     (layout.old_fingerprint(pkg), layout.fingerprint(pkg))
 }
index 4260ab34f0615a26b374d806f4de7ac0c3a64cc3..f1428c57ede1b462016ae1ba66eb9e1dbf4db579 100644 (file)
@@ -97,9 +97,6 @@ pub fn compile_targets<'a>(env: &str, targets: &[&'a Target], pkg: &'a Package,
         try!(compile(targets.as_slice(), dep, compiled, &mut cx, &mut queue));
     }
 
-    if pkg.get_package_id() == resolve.root() {
-        cx.primary();
-    }
     try!(compile(targets, pkg, true, &mut cx, &mut queue));
 
     // Now that we've figured out everything that we're going to do, do it!
@@ -205,7 +202,7 @@ fn compile_custom(pkg: &Package, cmd: &str,
     let mut cmd = cmd.split(' ');
     // TODO: this shouldn't explicitly pass `KindTarget` for dest/deps_dir, we
     //       may be building a C lib for a plugin
-    let layout = cx.layout(KindTarget);
+    let layout = cx.layout(pkg, KindTarget);
     let output = layout.native(pkg);
     let old_output = layout.proxy().old_native(pkg);
     let mut p = process(cmd.next().unwrap(), pkg, cx)
@@ -253,18 +250,14 @@ fn rustc(package: &Package, target: &Target,
          cx: &mut Context, req: PlatformRequirement)
          -> CargoResult<Vec<(Work, Kind, String)> >{
     let crate_types = target.rustc_crate_types();
-    let root = package.get_root();
-
-    log!(5, "root={}; target={}; crate_types={}; verbose={}; req={}",
-         root.display(), target, crate_types, cx.primary, req);
-
     let rustcs = try!(prepare_rustc(package, target, crate_types, cx, req));
 
     Ok(rustcs.into_iter().map(|(rustc, kind)| {
         let name = package.get_name().to_string();
         let desc = rustc.to_string();
         let is_path_source = package.get_package_id().get_source_id().is_path();
-        let show_warnings = cx.primary || is_path_source;
+        let show_warnings = package.get_package_id() == cx.resolve.root() ||
+                            is_path_source;
         let rustc = if show_warnings {rustc} else {rustc.arg("-Awarnings")};
 
         (proc() {
@@ -304,7 +297,7 @@ fn rustdoc(package: &Package, target: &Target,
            cx: &mut Context) -> CargoResult<(Work, String)> {
     let kind = KindTarget;
     let pkg_root = package.get_root();
-    let cx_root = cx.layout(kind).proxy().dest().join("doc");
+    let cx_root = cx.layout(package, kind).proxy().dest().join("doc");
     let rustdoc = process("rustdoc", package, cx).cwd(pkg_root.clone());
     let rustdoc = rustdoc.arg(target.get_src_path())
                          .arg("-o").arg(cx_root)
@@ -313,7 +306,7 @@ fn rustdoc(package: &Package, target: &Target,
 
     log!(5, "commands={}", rustdoc);
 
-    let primary = cx.primary;
+    let primary = package.get_package_id() == cx.resolve.root();
     let name = package.get_name().to_string();
     let desc = rustdoc.to_string();
     Ok((proc() {
@@ -408,7 +401,7 @@ fn build_base_args(cx: &Context,
 fn build_plugin_args(mut cmd: ProcessBuilder, cx: &Context, pkg: &Package,
                      target: &Target, kind: Kind) -> ProcessBuilder {
     cmd = cmd.arg("--out-dir");
-    cmd = cmd.arg(cx.layout(kind).root());
+    cmd = cmd.arg(cx.layout(pkg, kind).root());
 
     let (_, dep_info_loc) = fingerprint::dep_info_loc(cx, pkg, target, kind);
     cmd = cmd.arg("--dep-info").arg(dep_info_loc);
@@ -436,9 +429,7 @@ fn build_plugin_args(mut cmd: ProcessBuilder, cx: &Context, pkg: &Package,
 fn build_deps_args(mut cmd: ProcessBuilder, target: &Target, package: &Package,
                    cx: &Context,
                    kind: Kind) -> CargoResult<ProcessBuilder> {
-    enum LinkReason { Dependency, LocalLib }
-
-    let layout = cx.layout(kind);
+    let layout = cx.layout(package, kind);
     cmd = cmd.arg("-L").arg(layout.root());
     cmd = cmd.arg("-L").arg(layout.deps());
 
@@ -455,9 +446,7 @@ fn build_deps_args(mut cmd: ProcessBuilder, target: &Target, package: &Package,
     }
 
     for &(pkg, target) in cx.dep_targets(package).iter() {
-        let pkgid = pkg.get_package_id();
-        let reason = if pkgid == cx.resolve.root() {LocalLib} else {Dependency};
-        cmd = try!(link_to(cmd, target, cx, kind, reason));
+        cmd = try!(link_to(cmd, pkg, target, cx, kind));
     }
 
     let mut targets = package.get_targets().iter().filter(|target| {
@@ -470,32 +459,28 @@ fn build_deps_args(mut cmd: ProcessBuilder, target: &Target, package: &Package,
                 continue;
             }
 
-            cmd = try!(link_to(cmd, target, cx, kind, LocalLib));
+            cmd = try!(link_to(cmd, package, target, cx, kind));
         }
     }
 
     return Ok(cmd);
 
-    fn link_to(mut cmd: ProcessBuilder, target: &Target,
-               cx: &Context, kind: Kind,
-               reason: LinkReason) -> CargoResult<ProcessBuilder> {
+    fn link_to(mut cmd: ProcessBuilder, pkg: &Package, target: &Target,
+               cx: &Context, kind: Kind) -> CargoResult<ProcessBuilder> {
         // If this target is itself a plugin *or* if it's being linked to a
         // plugin, then we want the plugin directory. Otherwise we want the
         // target directory (hence the || here).
-        let layout = cx.layout(match kind {
+        let layout = cx.layout(pkg, match kind {
             KindPlugin => KindPlugin,
             KindTarget if target.get_profile().is_plugin() => KindPlugin,
             KindTarget => KindTarget,
-        }).proxy();
+        });
 
         for filename in try!(cx.target_filenames(target)).iter() {
             let mut v = Vec::new();
             v.push_all(target.get_name().as_bytes());
             v.push(b'=');
-            match reason {
-                Dependency => v.push_all(layout.deps().as_vec()),
-                LocalLib => v.push_all(layout.dest().as_vec()),
-            }
+            v.push_all(layout.root().as_vec());
             v.push(b'/');
             v.push_all(filename.as_bytes());
             cmd = cmd.arg("--extern").arg(v.as_slice());
@@ -507,7 +492,7 @@ fn build_deps_args(mut cmd: ProcessBuilder, target: &Target, package: &Package,
 pub fn process<T: ToCStr>(cmd: T, pkg: &Package, cx: &Context) -> ProcessBuilder {
     // When invoking a tool, we need the *host* deps directory in the dynamic
     // library search path for plugins and such which have dynamic dependencies.
-    let layout = cx.layout(KindPlugin);
+    let layout = cx.layout(pkg, KindPlugin);
     let mut search_path = DynamicLibrary::search_path();
     search_path.push(layout.deps().clone());
 
index e739f3463aa1845a204a90d06f3c0b70d7d1d55e..07a7656db663eaef0c816ff98807265223dc09e4 100644 (file)
@@ -1025,3 +1025,31 @@ test!(almost_cyclic_but_not_quite {
     assert_that(p.process(cargo_dir().join("cargo")).arg("test"),
                 execs().with_status(0));
 })
+
+test!(build_then_selective_test {
+    let p = project("a")
+        .file("Cargo.toml", r#"
+            [package]
+            name = "a"
+            version = "0.0.1"
+            authors = []
+
+            [dependencies.b]
+            path = "b"
+        "#)
+        .file("src/lib.rs", "extern crate b;")
+        .file("src/main.rs", "extern crate b; extern crate a; fn main() {}")
+        .file("b/Cargo.toml", r#"
+            [package]
+            name = "b"
+            version = "0.0.1"
+            authors = []
+        "#)
+        .file("b/src/lib.rs", "");
+
+    assert_that(p.cargo_process("build"), execs().with_status(0));
+    p.root().move_into_the_past().unwrap();
+    assert_that(p.process(cargo_dir().join("cargo")).arg("test")
+                 .arg("-p").arg("b"),
+                execs().with_status(0));
+})